import LR1Grammar
import queue


class idn:

    def __init__(self, value, addr):
        self.value = value
        self.addr = addr


class option:

    def __init__(self, op, obj1, obj2, result, ID):
        self.op = op
        self.obj1 = obj1
        self.obj2 = obj2
        self.result = result
        self.id = ID
        self.nextID = '_'
        self.isSwitch = False
        self.switchType = True
        self.accept = False
        self.trueList = []
        self.falseList = []

    def toString(self):
        print str(self.id) + ': (' + str(self.op) + ', ' + str(self.obj1.addr) + \
            ', ' + str(self.obj2.addr) + ', ' + \
            str(self.result.addr) + ', ' + str(self.nextID) + ')'


class SDT:

    def __init__(self, tree, turples, turples2Tokens, idnList):
        self.tree = tree
        self.turples = turples
        self.turples2Tokens = turples2Tokens
        self.idnList = idnList
        self.transIndex = 0
        self.expNum = 0
        self.idnSet = []
        self.expSet = []
        idnAddr = 0
        for value in self.idnList:
            self.idnSet.append(idn(value, 't'+str(idnAddr)))
            idnAddr += 1

    def gen(self):
        return idn('_', 't'+str(len(self.idnSet)))

    def expression(self, node):
        result = []
        if len(node.children) == 3:
            if node.children[1].value == 'E':
                result = self.expression(node.children[1])
            else:
                tempList1 = self.expression(node.children[0])
                tempList2 = self.expression(node.children[2])
                if type(tempList1) == list and type(tempList2) == list:
                    result += tempList1
                    result += tempList2
                    combineOption = option(str(node.children[1].value), tempList1[len(
                        tempList1)-1].result, tempList2[len(tempList2)-1].result, self.gen(), self.expNum)
                    self.expNum += 1
                    result += [combineOption]
                elif type(tempList1) == list and type(tempList2) == idn:
                    result += tempList1
                    combineOption = option(str(node.children[1].value), tempList1[len(
                        tempList1)-1].result, tempList2.addr, self.gen(), self.expNum)
                    self.expNum += 1
                    result += [combineOption]
                elif type(tempList1) == idn and type(tempList2) == list:
                    result += tempList2
                    combineOption = option(str(node.children[1].value), tempList1.addr, tempList2[len(
                        tempList2)-1].result, self.gen(), self.expNum)
                    self.expNum += 1
                    result += [combineOption]
                elif type(tempList1) == idn and type(tempList2) == idn:
                    combineOption = option(str(
                        node.children[1].value), tempList1.addr, tempList2.addr, self.gen(), self.expNum)
                    self.expNum += 1
                    result += [combineOption]
                if node.children[1].value == '>' or node.children[1].value == '<':
                    result[0].isSwitch = True
                    tempOp = option('_', '_', '_', '_', self.expNum)
                    self.expNum += 1
                    tempOp.isSwitch = True
                    tempOp.switchType = False
                    result += [tempOp]
        elif len(node.children) == 1:
            # result = self.idnSet[0] # Todo
            result = self.gen()
            # print self.gen()
            # print result
        # print result
        return result

    def analysis(self):
        node = self.tree[0]
        optionStack = []
        ID = 0
        trueQueue = queue.Queue()
        falseStack = []
        while node.value != '$':
            if node.value == 'S\'':
                node = node.children[0]
                continue
            elif node.value == 'S':
                if len(node.children) > 3:
                    node = node.children[0]
                elif len(node.children) == 3:
                    node = node.children[0]
                elif len(node.children) == 0:
                    optionStack.append(option('_', '_', '_', '_', self.expNum))
                    self.expNum += 1
                    while node.parent.children.index(node) == len(node.parent.children) - 1:
                        node = node.parent
                    node = node.parent.children[node.parent.children.index(
                        node)+1]
            elif node.value == 'E':
                expressions = self.expression(node)
                if not trueQueue.empty():
                    if list(trueQueue)[0].accept:
                        self.expSet[self.expSet.index(
                            list(trueQueue)[0])].nextID = len(self.expSet)
                if len(falseStack) > 0:
                    if falseStack[len(falseStack)-1].accept:
                        self.expSet[self.expSet.index(
                            falseStack[len(falseStack)-1])].nextID = len(self.expSet)
                self.expSet += expressions
                for exp in expressions:
                    if exp.isSwitch:
                        if exp.switchType:
                            trueQueue.put(exp)
                        else:
                            falseStack.append(exp)
                nodeIndex = node.parent.children.index(node)
                node = node.parent.children[nodeIndex+2]
            elif node.value == '{':
                nodeIndex = node.parent.children.index(node)
                node = node.parent.children[nodeIndex+1]
                for exp in list(trueQueue):
                    if not exp.accept:
                        exp.accept = True
                        break
            elif node.value == '}':
                nodeIndex = node.parent.children.index(node)
                node = node.parent.children[nodeIndex+1]
                for i in range(len(falseStack)):
                    if not falseStack[len(falseStack)-i-1].accept:
                        falseStack[len(falseStack)-i-1].accept = True
                        break
            elif node.value == 'while':
                node = node.parent.children[2]
            elif node.value == 'if':
                node = node.parent.children[2]
            else:
                if node.value not in ['(', ')', ';']:
                    tokenIndex = self.turples2Tokens.index(node.value)
                    return '[line ' + str(self.turples[tokenIndex][0]) + ']: Error'
                else:
                    nodeIndex = node.parent.children.index(node)
                    node = node.parent.children[nodeIndex+1]
        content = ''
        for exp in self.expSet:
            content += str(exp.id) + exp.toString()
        return content


if __name__ == "__main__":
    pass
